fix(platform-objects): the zh-CN dashboard metadata-form subtree says what its source says - #14926
Conversation
…on description `metadataForms.dashboard.sections.layout.description` read 「栅格与响应式」 against a source of "Grid sizing and refresh cadence." — it named a responsiveness control the section does not hold and omitted the refresh cadence it does. Now 「栅格尺寸与刷新间隔」, matching the bundle's own terms for `columns` and `refreshInterval`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
…ce says Four more leaves of `metadataForms.dashboard` described the Studio dashboard property panel in terms `packages/spec/src/ui/dashboard.form.ts` does not use — each naming a concept the source omits while dropping one it names: sections.basics.description 「名称与图标」 -> 「仪表板标识与描述」 sections.widgets.description 「图表、指标、列表等」 -> 「放置在栅格上的卡片与图表」 sections.filters.description 「全局筛选与日期范围」 -> 「应用到所有组件的默认筛选与全局筛选」 fields.header.helpText 「标题、操作按钮与筛选」 -> 「仪表板页眉配置(title、subtitle、actions)」 `basics` promised an icon input, and the dashboard schema declares no icon key at all (the only `icon` under `dashboard.zod.ts` is per header action) — the same defect class as the layout leaf this branch already corrected, which promised a responsive-breakpoint control. The other three swapped which concepts the section covers: widgets is cards and charts on the grid, not metrics and lists; filters is default plus global filters across widgets, not the date range (that is the separate `dateRange` field); and the header carries a subtitle, not filters. The replacements reuse this bundle's own established terms and mirror es-ES / ja-JP, both of which are correct at all five leaves. The two changesets are consolidated into one so the subtree's correction lands as a single release note row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
…-cn-dashboard-sections-layout
CI triage —
|
|
Re-run came back green — The Generated by Claude Code |
Part of #14587.
The zh-CN
metadataForms.dashboardsubtree now says what its source(
packages/spec/src/ui/dashboard.form.ts) says. Five leaves, which is thescope the card's triage ruling set: two named leaves plus a sweep bounded to the
dashboardsubtree.sections.layout.description:21Grid sizing and refresh cadence.sections.basics.description:11Dashboard identity and description.sections.widgets.description:32Cards and charts placed on the grid.sections.filters.description:39Default and global filters applied across widgets.fields.header.helpText:27Dashboard header config (title, subtitle, actions)Each old value named a concept the source omits while dropping one it names.
Wording is taken from this bundle's own established terms —
gridis 栅格,widgetsis 组件,identityis 标识 (as in 应用标识与启用状态 forApp identity and activation.), and the literal key list is rendered(title、subtitle、actions)the way
page.fields.layout.helpTextrenders(header、main、sidebar、footer).es-ES and ja-JP are correct at all five and were the reference.
Why
Part ofand not a closing keywordPart 2 of the card — whether drifted leaves can be reported at all — stays open
after this PR, so merging this must not close the card. That half is now tracked
separately as #14931 (⛔ not #14929 — an earlier comment on the card cited that
number before the card existed and has since corrected itself; #14929 is an
unrelated issue), and the remaining stale leaves outside this subtree belong to
it, not here.
A. ⭐ Two of the five pointed authors at controls that do not exist
sections.layoutpromised a responsive-breakpoint input; the section holdscolumns,gap,refreshIntervalandheader(dashboard.form.ts:19-29), andthe refresh cadence it does hold went unnamed.
sections.basicspromised an icon input. That section holdsname,labeland
description(dashboard.form.ts:9-18), and the dashboard schema declaresno icon key at all — the only
iconunderpackages/spec/src/ui/dashboard.zod.tsis per header action (
:97,Icon identifier for the action button). So thestring asserted a UI element that has never existed anywhere on this form.
The other three swapped which concepts the section covers: widgets is cards and
charts on the grid, not metrics and lists; filters is default plus global filters
across widgets, not the date range (that is the separate
dateRangefield, whoseown helpText already says so); and the header carries a subtitle, not filters.
B. All five were still stale at the branch head, and no source moved
Every source string is byte-identical across that file's only two commits —
c7707850d(2026-05-28, file creation) and12a19a88a(2026-07-30, which onlyremoved inert keys from the Advanced section). Verified by reading both blobs,
not inferred.
⇒ Not drift after a source edit — a mistranslation at authoring time. All three
locales were seeded with the English verbatim (
ae2da1e7d); es-ES and ja-JP werethen translated from it (
874cb084e), while zh-CN alone was overwritten the sameday by
e0077ea36, which imported the pre-consolidationsrc/metadata-translations/zh-CN.tsoverlay (746 lines deleted) and neverreconciled it against the seeded English.
C. Subtree sweep: the
dashboardsubtree holds 30 leaves, and no others are staleBoth bundles were flattened to dotted leaf paths (767 each, key sets identical
across all four locales) and the 30 under
dashboardwere compared leaf by leafagainst
en. Beyond the five above, none asserts a concept the source omits ordrops one it names. Two near-misses are recorded so the threshold is auditable
rather than asserted, and neither was touched:
sections.advanced.description— 性能与无障碍 forAccessibility and performance tuning.Same two concepts, order reversed. Accurate.fields.header.label— 页眉 forHeader. A narrower term than es-ESEncabezado/ ja-JP ヘッダー, but it names the same region and asserts nothingextra. Left as the bundle's own established term, and reused in the helpText
above so the label and its help text share one vocabulary.
D. ⭐ The gate blindness is now PROVEN, not assumed — a control was added
The previous round measured all three i18n gates green with a stale string in
place. A green ablation alone cannot distinguish "the gate is blind" from "the
gate never read this file", so this round ran a positive control first: the
same leaf, but with the KEY deleted rather than the value made wrong.
Leg 1 going red is what makes leg 2 a reading:
check:i18ndemonstrably parsesthis exact file from disk, with no rebuild in between, and still returns OK on a
wrong value. ⇒ No gate fired on any of the four new corrections — a
re-confirmation of the previous round's finding, with the boundary now drawn
precisely: the gate detects a missing KEY (a fresh extract refills it, which is
drift) and is blind to a wrong VALUE, because merge mode treats any non-empty
value as already-translated. Both legs restored from
HEADwith blob equalityasserted, and the script carried a
trap ... EXIT INT TERMrestoring by absolutepath.
E. The producer was established before the file was hand-edited
The triage named the trap: do not hand-edit a regenerated bundle. Confirmed by
running the real producer, not by reading its docstring:
Merge mode preserves every hand-edited leaf value, so the documented
regeneration command reproduces this commit byte for byte.
zh-CN.source-hashes.generated.tsis unchanged and stays correct: these five leaves are legacy-trusted, carrying no
digest before or after, because none is a byte copy of any source revision.
Gates
Derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(no path arguments). The first derivation warned STALE TREE, so
origin/mainwasmerged and the family re-derived on the merged tree: 35 commands over the same
2-path change set, identical list. Run at
236b66e93, the final commit, andre-run there after the merge. All green except three that could not measure:
node scripts/check-test-completeness.mjs— exit 3, NOT MEASURED (needs asaved
turbo run testlog; the script itself says to record it as NOT MEASUREDwhen running the family locally). CI tees one.
pnpm check:dual-build-cjs-loads— exit 3, PREREQUISITE NOT MET (reads builtoutput for packages this change does not touch; needs a whole-repo build).
node scripts/pm/check-half-states.mjs— exit 3, NOT MEASURED (needsrepo-scoped GitHub egress, which this seat's session gate refuses). Its
pnpm check:pm-half-statessibling is green.pnpm check:i18nfirst returned exit 1 as PREREQUISITE NOT MET — the built CLIwas absent because the earlier build used the dependencies-of filter
(
@objectstack/cli^...), which does not build the CLI itself. Its named closurewas run and the gate is green; the same happened once for
check:i18n-coverage, cleared the same way. Neither exit was a finding.Also run:
pnpm --filter @objectstack/platform-objects run typecheck(green;tsc --listFilesconfirms the edited file is in the program, 1 hit) and thatpackage's full
test(33 files, 518 tests, all pass), plus its translationssuite alone (7 files, 85 tests) which carries the vocabulary and bundle-ownership
pins.
node scripts/pm/check-governed-merges.mjs --teston the final two-filelist: NOT governed, ordinary queue landing applies. Heavy runs went through
scripts/pm/os-verify-lock.sh.The two changesets on this branch were consolidated into one so the subtree's
correction lands as a single release-note row.
Authored by Claude Code in session
0112hMx9hjJ9BgB28X97DS68(https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68).
🤖 Generated with Claude Code
Generated by Claude Code